<template>
  <Row :gutter="8">
    <template v-for="c in configs" :key="c.key">
      <Col v-bind="c.wrapperCol" v-if="c.when(value)">
        <FormItem v-bind="c.formItemAttrs" :label-col="c.labelCol">
          <Switch
            v-if="c.type.name === 'ASwitch'"
            v-bind="c.componentAttrs"
            :checked="Boolean(value[c.key])"
            @update:checked="
              (e) => {
                handleChange({
                  key: config.key,
                  value: config.componentAttrs?.useNumber ? +e : e,
                });
                config.componentAttrs.onChange?.({ update: handleChange, value: value });
              }
            "
          />
          <component
            v-else
            :is="c.type"
            v-bind="c.componentAttrs"
            :raw="c.raw"
            :config="c"
            :value="value[c.key]"
            @update:value="(e:string|number|any) => {
              if(e?.key) {
                handleChange({ key: e.key, value: e.value });
              } else {
                handleChange({ key: c.key, value: e });
              }
              c.componentAttrs.onChange?.({ update:handleChange, value: value })
            }"
          />
        </FormItem>
      </Col>
    </template>
  </Row>
</template>
<script lang="tsx" setup>
import {
  Col, Form, Row, Switch,
} from 'ant-design-vue';
import { computed, type PropType } from 'vue';

import { type FormItemConfig } from './ConfigFormType';

const FormItem = Form.Item;
const props = defineProps({
  readonly: {
    type: Boolean,
    default: false,
  },
  disabled: {
    type: Boolean,
    default: false,
  },
  config: {
    type: Object as PropType<{
      key: string;
      name: (string | number)[];
      labelCol?: any;
      wrapperCol?: any;
      componentAttrs?: any;
      formItemAttrs?: any;
      raw: FormItemConfig;
    }>,
    default: () => ({
      key: '',
      name: [],
      labelCol: {},
      wrapperCol: {},
      componentAttrs: {},
      formItemAttrs: {},
      raw: {},
    }),
  },
});
const value = defineModel('value', {
  type: Object as PropType<any>,
  default: () => ({}),
});
const configs = computed(() => {
  const childrenConfig = props.config.raw.children || [];
  return childrenConfig.map((child: FormItemConfig) => {
    const {
      wrapperCol, labelCol, when, type, key = '', attrs, children, model, ...rest
    } = child;
    const name = [...props.config.name, key];
    const formItemAttrs = {
      name,
      model,
      ...rest,
    };
    const componentAttrs = {
      ...attrs,
      disabled: Boolean(props.disabled || attrs?.disabled),
      readonly: Boolean(props.readonly || attrs?.readonly),
    } as Record<string, any>;
    return {
      key,
      name,
      type,
      children,
      when: when || (() => true),
      labelCol: labelCol || props.config.labelCol || {},
      wrapperCol: wrapperCol || props.config.wrapperCol || {},
      componentAttrs,
      formItemAttrs,
      raw: child,
    };
  });
});

const handleChange = (data: any) => {
  value.value[data.key] = data.value;
};
</script>

<style lang="less" scoped></style>
